package com.keyi.baidu_trace

import android.content.Context
import android.util.Log
import androidx.annotation.NonNull
import com.baidu.trace.LBSTraceClient
import com.baidu.trace.api.entity.AddEntityRequest
import com.baidu.trace.api.entity.AddEntityResponse
import com.baidu.trace.api.entity.OnEntityListener
import com.baidu.trace.api.entity.UpdateEntityRequest
import com.baidu.trace.api.entity.UpdateEntityResponse
import com.baidu.trace.api.track.OnTrackListener
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import com.baidu.trace.model.OnTraceListener
import com.baidu.trace.Trace
import com.baidu.trace.model.PushMessage

/** BaiduTracePlugin */
class BaiduTracePlugin : FlutterPlugin, MethodCallHandler {
    /// The MethodChannel that will the communication between Flutter and native Android
    ///
    /// This local reference serves to register the plugin with the Flutter Engine and unregister it
    /// when the Flutter Engine is detached from the Activity
    private lateinit var channel: MethodChannel
    private val TAG="BaiduTracePlugin"

    private var mLBSTraceClient: LBSTraceClient? = null
    private var mContext: Context? = null

    override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        mContext = flutterPluginBinding.getApplicationContext()
        channel = MethodChannel(flutterPluginBinding.binaryMessenger, "baidu_trace")
        channel.setMethodCallHandler(this)
    }

    override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: MethodChannel.Result) {
        when (call.method) {
            "getPlatformVersion" -> result.success("Android ${android.os.Build.VERSION.RELEASE}");
            "initSdk" -> {
                if (mContext != null) {
                    try {
                        LBSTraceClient.setAgreePrivacy(mContext, true)
                        mLBSTraceClient = LBSTraceClient(mContext)
                        mLBSTraceClient?.setInterval(5, 10)
                        result.success(true)
                    } catch (e: Exception) {
                        e.printStackTrace()
                        result.success(false)
                    }
                } else {
                    result.success(false)
                }
            }
            "addEntity" -> addEntity(call, result)
            "updateEntity" -> updateEntity(call, result)
            "startTrace" -> startTrace(call, result)
            "stopTrace" -> stopTrace(call, result)
            "startGather" -> startGather(result)
            "stopGather" -> stopGather(result)
            else -> result.notImplemented()
        }
    }

    /**
     * 添加实体信息
     */
    private fun addEntity(call: MethodCall, result: MethodChannel.Result) {
        if (call == null || call.arguments == null || mLBSTraceClient == null) {
            result.success(false)
            return
        }

        val addEntityRequest = AddEntityRequest()
        addEntityRequest.setTag(call.argument("tag")!!)
        addEntityRequest.setServiceId(call.argument("serviceId")!!)
        addEntityRequest.setEntityName(call.argument("entityName")!!)
        addEntityRequest.setEntityDesc(call.argument("entityDesc") ?: "")
        addEntityRequest.setColumns(call.argument("custom"))

        mLBSTraceClient?.addEntity(
            addEntityRequest,
            onEntityListener
        )
        result.success(true)
    }

    /**
     * 修改实体信息
     */
    private fun updateEntity(call: MethodCall, result: MethodChannel.Result) {
        if (call == null || call.arguments == null || mLBSTraceClient == null) {
            result.success(false)
            return
        }

        val updateEntityRequest = UpdateEntityRequest()
        updateEntityRequest.setTag(call.argument("tag")!!)
        updateEntityRequest.setServiceId(call.argument("serviceId")!!)
        updateEntityRequest.setEntityName(call.argument("entityName")!!)
        updateEntityRequest.setEntityDesc(call.argument("entityDesc") ?: "")
        updateEntityRequest.setColumns(call.argument("custom"))
        mLBSTraceClient?.updateEntity(
            updateEntityRequest,
            onEntityListener
        )
        result.success(true)
    }

    /**
     * 开启猎鹰服务
     */
    private fun startTrace(call: MethodCall, result: MethodChannel.Result) {
        if (call == null || call.arguments == null || mLBSTraceClient == null) {
            result.success(false)
            return
        }
        val trace =
            com.baidu.trace.Trace(call.argument("serviceId")!!, call.argument("entityName")!!)
        mLBSTraceClient?.startTrace(
            trace,
            onTraceListener
        )
        result.success(true)
    }

    /**
     * 停止猎鹰服务
     */
    private fun stopTrace(call: MethodCall, result: MethodChannel.Result) {
        if (call == null || call.arguments == null || mLBSTraceClient == null) {
            result.success(false)
            return
        }
        val trace =
            com.baidu.trace.Trace(call.argument("serviceId")!!, call.argument("entityName")!!)
        mLBSTraceClient?.stopTrace(
            trace,
            onTraceListener
        )
        result.success(true)
    }

    /**
     * 开始上报轨迹
     */
    private fun startGather(result: MethodChannel.Result) {
        if (mLBSTraceClient == null) {
            result.success(false)
            return
        }
        mLBSTraceClient?.startGather(onTraceListener)
        result.success(true)
    }

    /**
     * 停止上报轨迹
     */
    private fun stopGather(result: MethodChannel.Result) {
        if (mLBSTraceClient == null) {
            result.success(false)
            return
        }
        mLBSTraceClient?.stopGather(onTraceListener)
        result.success(true)
    }

    override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
        channel.setMethodCallHandler(null)
        mLBSTraceClient?.clear()
    }

    /**
     * 实体操作回调
     */
    private val onEntityListener = object : OnEntityListener() {
        override fun onAddEntityCallback(addEntityResponse: AddEntityResponse?) {
            Log.i(TAG, "onAddEntityCallback: $addEntityResponse")
            if (addEntityResponse == null || mLBSTraceClient == null) {
                return
            }
            channel.invokeMethod(
                "addEntityCallBack",
                hashMapOf<String, Any>(
                    "tag" to addEntityResponse.getTag(),
                    "status" to addEntityResponse.getStatus(),
                    "message" to addEntityResponse.getMessage()
                )
            )
        }

        override fun onUpdateEntityCallback(response: UpdateEntityResponse?) {
            Log.i(TAG, "onUpdateEntityCallback: $response")
            if (response == null || mLBSTraceClient == null) {
                return
            }

            channel.invokeMethod(
                "updateEntityCallBack",
                hashMapOf<String, Any>(
                    "tag" to response.getTag(),
                    "status" to response.getStatus(),
                    "message" to response.getMessage()
                )
            )
        }
    }

    /**
     * 轨迹操作回调
     */
    private val onTraceListener = object : OnTraceListener {
        override fun onBindServiceCallback(status: Int, message: String) {
            Log.i(TAG, "onBindServiceCallback: $status--$message")
            channel.invokeMethod(
                "onBindServiceCallback",
                hashMapOf<String, Any>(
                    "status" to status,
                    "message" to message
                )
            )
        }

        override fun onInitBOSCallback(status: Int, message: String) {

        }

        override fun onStartGatherCallback(status: Int, message: String) {
            Log.i(TAG, "onStartGatherCallback: $status--$message")
            channel.invokeMethod(
                "onStartGatherCallback",
                hashMapOf<String, Any>(
                    "status" to status,
                    "message" to message
                )
            )
        }

        override fun onStartTraceCallback(status: Int, message: String) {
            Log.i(TAG, "onStartTraceCallback: $status--$message")
            channel.invokeMethod(
                "onStartTraceCallback",
                hashMapOf<String, Any>(
                    "status" to status,
                    "message" to message
                )
            )
        }

        override fun onStopGatherCallback(status: Int, message: String) {
            Log.i(TAG, "onStopGatherCallback: $status--$message")
            channel.invokeMethod(
                "onStopGatherCallback",
                hashMapOf<String, Any>(
                    "status" to status,
                    "message" to message
                )
            )
        }

        override fun onStopTraceCallback(status: Int, message: String) {
            Log.i(TAG, "onStopTraceCallback: $status--$message")
            channel.invokeMethod(
                "onStopTraceCallback",
                hashMapOf<String, Any>(
                    "status" to status,
                    "message" to message
                )
            )
        }

        override fun onTraceDataUploadCallBack(
            status: Int,
            message: String,
            length: Int,
            time: Int
        ) {

        }

        override fun onPushCallback(messageNo: Byte, message: PushMessage) {

        }
    }
}
